﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Security.Cryptography;
using System.IO;

/// <summary>
/// Encryption service based on examples at MSDN
/// </summary>
public class Encryption : IEncryptionService
{
    // create salt for the encryption
    private static byte[] _encryptionSalt = Encoding.ASCII.GetBytes("mysaltstring");

    public Encryption()
    {
    }

    public string Encrypt(string textToEncrypt, string sharedSecret)
    {
        // final encrypted string
        string returnString = null;

        if (string.IsNullOrEmpty(textToEncrypt))
            throw new ArgumentNullException("stringToEncrypt");
        if (string.IsNullOrEmpty(sharedSecret))
            throw new ArgumentNullException("sharedSecret");

        // object used to encrypt string
        RijndaelManaged rm = null;

        try
        {
            // generate key from sharedSecret and encryptionSalt
            Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(sharedSecret, _encryptionSalt);

            rm = new RijndaelManaged();
            rm.Key = rfcKey.GetBytes(rm.KeySize / 8);
            rm.IV = rfcKey.GetBytes(rm.BlockSize / 8);

            // Create encryptor
            ICryptoTransform encryptor = rm.CreateEncryptor(rm.Key, rm.IV);

            // Create the streams used for encryption.
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                    {
                        // Write string to the stream.
                        sw.Write(textToEncrypt);
                    }
                }
                returnString = Convert.ToBase64String(ms.ToArray());
            }
        }
        finally
        {
            if (rm != null)
                rm.Clear();
        }

        // Return the encrypted bytes from the memory stream.
        return returnString;
    }

    public string Decrypt(string encryptedString, string sharedSecret)
    {
        // final decrypted string
        string unencryptedString = null;

        if (string.IsNullOrEmpty(encryptedString))
            throw new ArgumentNullException("encryptedString");
        if (string.IsNullOrEmpty(sharedSecret))
            throw new ArgumentNullException("sharedSecret");

        // object used to decrypt string
        RijndaelManaged rm = null;

        try
        {
            // generate key from sharedSecret and encryptionSalt
            Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(sharedSecret, _encryptionSalt);

            rm = new RijndaelManaged();
            rm.Key = rfcKey.GetBytes(rm.KeySize / 8);
            rm.IV = rfcKey.GetBytes(rm.BlockSize / 8);

            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = rm.CreateDecryptor(rm.Key, rm.IV);

            byte[] bytes = Convert.FromBase64String(encryptedString);
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sr = new StreamReader(cs))

                        // decrypt bytes and put in unencryptedString
                        unencryptedString = sr.ReadToEnd();
                }
            }
        }
        finally
        {
            if (rm != null)
                rm.Clear();
        }

        // return unencrypted string
        return unencryptedString;
    }
}
